home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / dev / devNet.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  23KB  |  820 lines

  1. /* 
  2.  * devNet.c --
  3.  *
  4.  *    Device interface to the network.  The routines here implement
  5.  *    filesystem devices for the various ethernet protocols.  Input
  6.  *    queues of received packets are maintainted here, although the
  7.  *    device has to be open before packets are queued.  There is a
  8.  *    different queue for each different ethernet protocol, and the
  9.  *    device unit number is used to identify the protocol.
  10.  *
  11.  *    TODO: this needs to be fixed to understand more than one network
  12.  *    interface.  It seems that at open time the correct interface
  13.  *    should be chosen.  Also, some interface-data needs to be passed
  14.  *    down to the output routines so they can choose the right interface.
  15.  *
  16.  * Copyright 1987 Regents of the University of California
  17.  * Permission to use, copy, modify, and distribute this
  18.  * software and its documentation for any purpose and without
  19.  * fee is hereby granted, provided that the above copyright
  20.  * notice appear in all copies.  The University of California
  21.  * makes no representations about the suitability of this
  22.  * software for any purpose.  It is provided "as is" without
  23.  * express or implied warranty.
  24.  */
  25.  
  26. #ifndef lint
  27. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/dev/devNet.c,v 9.10 92/06/03 22:54:22 voelker Exp $ SPRITE (Berkeley)";
  28. #endif not lint
  29.  
  30.  
  31. #include <sprite.h>
  32. #include <stdio.h>
  33. #include <net.h>
  34. #include <fs.h>
  35. #include <vm.h>
  36. #include <fsio.h>
  37. #include <devNet.h>
  38. #include <user/netInet.h>
  39. #include <stdlib.h>
  40. #include <sync.h>
  41. #include <fsioDevice.h>
  42. #include <user/net.h>
  43. #include <bstring.h>
  44.  
  45. Boolean devNetDebug = FALSE;
  46.  
  47. /*
  48.  * The  packets are kept in a circular queue whose length is a power of 2.
  49.  * Stuff gets added to the queues at interrupt time so removal requires
  50.  * synchronization with MASTER_LOCK/UNLOCK.
  51.  */
  52.  
  53. #define PACKET_QUEUE_LEN    16
  54. typedef struct {
  55.     int        head;
  56.     int        tail;
  57.     Address    packet[PACKET_QUEUE_LEN];
  58.     int        size[PACKET_QUEUE_LEN];
  59. } PacketQueue;
  60.  
  61. /*
  62.  * A circular queue is full if its tail is right in front of its
  63.  * head (mod length). A queue is empty if its tail is its head.
  64.  */
  65.  
  66. #define NextTail(queue)        (((queue).tail + 1) & (PACKET_QUEUE_LEN -1))
  67. #define NextHead(queue)        (((queue).head + 1) & (PACKET_QUEUE_LEN -1))
  68.  
  69. #define QueueFull(queue)    (NextTail(queue) == (queue).head)
  70. #define QueueEmpty(queue)       ((queue).tail == (queue).head)
  71.  
  72. /*
  73.  * Event counters kept on a per-device basis.
  74.  */
  75. typedef struct DeviceStats {
  76.     int        shorts;        /* Number of short packets received */
  77.     int        drops;        /* Number of packets dropped when queue full */
  78. } DeviceStats;
  79.  
  80. /*
  81.  * State for the devices.  They are linked together and scanned when
  82.  * a packet is received.  Packets with protocols that don't match any
  83.  * of the protocols in this list will be dropped.
  84.  */
  85.  
  86. typedef struct DeviceState {
  87.     List_Links        links;
  88.     Net_Interface     *interPtr;    /* Interface associated with the 
  89.                      * device; */
  90.     int            protocol;    /* Protocol associated with device. */
  91.     Boolean        kernel;        /* TRUE if kernel is using this proto */
  92.     PacketQueue        queue;        /* Queue of received packets */
  93.     DeviceStats        stats;        /* Event counters */
  94.     Fs_NotifyToken    fsReadyToken;    /* Used for filesystem callback that
  95.                      * notifies waiting processes that
  96.                      * packets are here */
  97.     int            (*inputProc)();    /* Used when the kernel is using the
  98.                      * protocol. */
  99. } DeviceState;
  100.  
  101.  
  102. /*
  103.  * Queue of all devices associated with an interface. 
  104.  */
  105.  
  106. typedef struct DeviceQueueState {
  107.     List_Links        links;        /* Queue of DeviceState structures
  108.                      * for this interface. */
  109.     Sync_Semaphore    mutex;        /* Synchronizes access to the queue. */
  110. } DeviceQueueState;
  111.  
  112. extern void        DevNetHandler();
  113. static ReturnStatus    ProtocolFromPacket();
  114. static ReturnStatus    ProtocolFromDevice();
  115. static DeviceQueueState *QueueFromInterface();
  116.  
  117. /*
  118.  *----------------------------------------------------------------------
  119.  *
  120.  * DevNet_FsOpen --
  121.  *
  122.  *    Open an ethernet protocol device.  Protocol state is set up and
  123.  *     linked in to a list of active protocols.  The protocol is marked
  124.  *     open to enable queueing of packets for this protocol.
  125.  *
  126.  * Results:
  127.  *    SUCCESS        - the operation was successful.
  128.  *    FS_FILE_BUSY    - the device was already opened.
  129.  *
  130.  * Side effects:
  131.  *    Storage for the protocol state is allocated and linked into
  132.  *    the list of active protocols.  
  133.  *
  134.  *----------------------------------------------------------------------
  135.  */
  136. /*ARGSUSED*/
  137. ReturnStatus
  138. DevNet_FsOpen(devicePtr, useFlags, data, flagsPtr)
  139.     Fs_Device   *devicePtr;    /* Device info, unit number == protocol */
  140.     int     useFlags;    /* Flags from the stream being opened */
  141.     Fs_NotifyToken  data;    /* Call-back for input notification */
  142.     int        *flagsPtr;    /* OUT: Device flags. */
  143. {
  144.     register int i;
  145.     unsigned int protocol;
  146.     ReturnStatus status = SUCCESS;
  147.     DeviceState        *statePtr;
  148.     DeviceQueueState *deviceQueuePtr;
  149.     Boolean        newFormat = FALSE;
  150.     Net_NetworkType    netType;
  151.     int            interface;
  152.     int            unitProto = 0;
  153.     Net_Interface    *interPtr;
  154.     DeviceState        *itemPtr;
  155.     int            maxSize;
  156.  
  157.     if (devNetDebug) {
  158.     printf("DevNet_FsOpen: opening device 0x%x 0x%x\n",
  159.         devicePtr->type, devicePtr->unit);
  160.     }
  161.     statePtr = (DeviceState *) (devicePtr->data);
  162.     if (statePtr == (DeviceState *) NIL) {
  163.     statePtr = (DeviceState *) malloc(sizeof(DeviceState));
  164.     bzero((char *) statePtr, sizeof(DeviceState));
  165.     List_InitElement((List_Links *) statePtr);
  166.     } else {
  167.     /*
  168.      * If the device has a state structure then it must be in use.
  169.      */
  170.     if (devNetDebug) {
  171.         printf("Extra open\n");
  172.     }
  173.     return FS_FILE_BUSY;
  174.     }
  175.     if (!(devicePtr->unit & DEV_NET_COMPAT_BIT)) {
  176.     interface = 0;
  177.     netType = NET_NETWORK_ETHER;
  178.     protocol = devicePtr->unit;
  179.     if (devNetDebug) {
  180.         printf("Device has old unit number\n");
  181.     }
  182.     } else {
  183.     int    tmp = (devicePtr->unit & ~DEV_NET_COMPAT_BIT);
  184.     netType = DEV_NET_NETTYPE_FROM_UNIT(tmp);
  185.     interface = DEV_NET_NUMBER_FROM_UNIT(tmp);
  186.     unitProto = DEV_NET_PROTO_FROM_UNIT(tmp);
  187.     if (devNetDebug) {
  188.         printf("Device has new unit number\n");
  189.     }
  190.     newFormat = TRUE;
  191.     }
  192.     interPtr = Net_GetInterface(netType, interface);
  193.     if (interPtr == (Net_Interface *) NIL) {
  194.     if (devNetDebug) {
  195.         printf("No interface.\n");
  196.     }
  197.     free((char *) statePtr);
  198.     return DEV_NO_DEVICE;
  199.     }
  200.     statePtr->interPtr = interPtr;
  201.     if (newFormat) {
  202.     status = ProtocolFromDevice(unitProto, interPtr, &protocol);
  203.     if (status != SUCCESS) {
  204.         if (devNetDebug) {
  205.         printf("No such protocol %d\n", protocol);
  206.         }
  207.         free((char *) statePtr);
  208.         return DEV_NO_DEVICE;
  209.     }
  210.     }
  211.     deviceQueuePtr = QueueFromInterface(interPtr);
  212.     switch(netType) {
  213.     case NET_NETWORK_ETHER: 
  214.         /*
  215.          * We keep the protocol number in network byte order so as to match
  216.          * the values coming off the net.
  217.          */
  218.         protocol = (unsigned int) 
  219.                 Net_HostToNetShort((unsigned short) protocol);
  220.         break;
  221.     }
  222.     statePtr->protocol = protocol;
  223.     /*
  224.      * Pre-allocate buffer space for the input queue.
  225.      * This is probably a bad idea for anything but an ethernet since
  226.      * packet sizes may get large.
  227.      */
  228.     switch(netType) {
  229.     case NET_NETWORK_ETHER:
  230.         maxSize = NET_ETHER_MAX_BYTES;
  231.         break;
  232.     case NET_NETWORK_ULTRA:
  233.         maxSize = NET_ULTRA_MAX_BYTES;
  234.         break;
  235.     case NET_NETWORK_FDDI:
  236.         maxSize = NET_FDDI_MAX_BYTES;
  237.         break;
  238.     default:
  239.         printf("DevNet_FsOpen: unknown net type %d\n", netType);
  240.         return DEV_NO_DEVICE;
  241.     }
  242.     for (i=0 ; i< PACKET_QUEUE_LEN ; i++) {
  243.     statePtr->queue.packet[i] = (Address) malloc (maxSize);
  244.     }
  245.  
  246.     /*
  247.      * Differentiate between user-level reads and the kernel.
  248.      * DevNetEtherHandler will handle packets differently in
  249.      * the two cases.  It notifies the user-level process, or
  250.      * it calls the kernel protocol handler.
  251.      */
  252.     if (useFlags & FS_USER) {
  253.     statePtr->kernel = FALSE;
  254.     statePtr->fsReadyToken = data;
  255.     } else {
  256.     statePtr->kernel = TRUE;
  257. #ifndef lint
  258.     statePtr->inputProc = (int(*)())data;
  259. #endif /* lint */
  260.     }
  261.     statePtr->queue.head = 0;
  262.     statePtr->queue.tail = 0;
  263.     devicePtr->data = (ClientData) statePtr;
  264.     MASTER_LOCK(&deviceQueuePtr->mutex);
  265.     LIST_FORALL((List_Links *) deviceQueuePtr, (List_Links *) itemPtr) {
  266.     if (itemPtr->protocol == protocol) {
  267.         panic("DevNet_FsOpen: found protocol already in use.\n");
  268.     }
  269.     }
  270.     List_Insert((List_Links *)statePtr, 
  271.     LIST_ATREAR((List_Links *) deviceQueuePtr));
  272.     Net_SetPacketHandler(interPtr, DevNetHandler);
  273.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  274.     if (devNetDebug) {
  275.     printf("DevNet_FsOpen: Open proto 0x%x status 0x%x\n", 
  276.             protocol, status);
  277.     }
  278.     return(status);
  279. }
  280.  
  281. /*
  282.  *----------------------------------------------------------------------
  283.  *
  284.  * DevNet_FsReopen --
  285.  *
  286.  *    Reopen an ethernet protocol device.  Call the regular
  287.  *    open routine to do all the work.
  288.  *
  289.  * Results:
  290.  *    SUCCESS        - the operation was successful.
  291.  *    FS_FILE_BUSY    - the device was already opened.
  292.  *
  293.  * Side effects:
  294.  *    Storage for the protocol state is allocated and linked into
  295.  *    the list of active protocols.  
  296.  *
  297.  *----------------------------------------------------------------------
  298.  */
  299. /*ARGSUSED*/
  300. ReturnStatus
  301. DevNet_FsReopen(devicePtr, refs, writers, data, flagsPtr)
  302.     Fs_Device   *devicePtr;    /* Device info, unit number == protocol */
  303.     int     refs;        /* Number of open network streams */
  304.     int        writers;    /* Number that are open for writing */
  305.     Fs_NotifyToken  data;    /* Call-back for input notification */
  306.     int        *flagsPtr;    /* OUT: Device flags. */
  307. {
  308.     int useFlags = FS_READ;
  309.  
  310.     if (writers) {
  311.     useFlags |= FS_WRITE;
  312.     }
  313.     return( DevNet_FsOpen(devicePtr, useFlags, data, flagsPtr) );
  314. }
  315.  
  316.  
  317. /*
  318.  *----------------------------------------------------------------------
  319.  *
  320.  * DevNetHandler --
  321.  *
  322.  *    Dispatcher for packets.  The list of active protocols
  323.  *    is scanned for a matching protocol.  If found, the packet is
  324.  *    enqueued for the protocol.
  325.  *
  326.  *    Note: This routine is called from the network interrupt routine.
  327.  *
  328.  * Results:
  329.  *    None.
  330.  *
  331.  * Side effects:
  332.  *    The packet is saved in the protocols queue (if there's room and
  333.  *    the protocol device is currently open).
  334.  *
  335.  *----------------------------------------------------------------------
  336.  */
  337.  
  338. /*ARGSUSED*/
  339. void
  340. DevNetHandler(interPtr, size, packetPtr)
  341.     Net_Interface    *interPtr;     /* Network interface. */
  342.     int            size;        /* Size of the packet. */
  343.     Address        packetPtr;    /* Pointer to the packet in the hardware
  344.                      * receive buffer. */
  345. {
  346.     register DeviceQueueState *deviceQueuePtr;
  347.     int    protocol;
  348.     DeviceState        *statePtr;
  349.     ReturnStatus    status;
  350.  
  351.  
  352.     deviceQueuePtr = (DeviceQueueState *) interPtr->devNetData;
  353.     if (deviceQueuePtr == (DeviceQueueState *) NIL) {
  354.     return;
  355.     }
  356.     status = ProtocolFromPacket(packetPtr, interPtr->netType, &protocol);
  357.     if (status != SUCCESS) {
  358.     printf("DevNetHandler: couldn't get protocol from packet.\n");
  359.     return;
  360.     }
  361.     if (devNetDebug) {
  362.     printf("DevNetHandler %d:%d 0x%x %d\n", interPtr->netType, 
  363.         interPtr->number, protocol, size);
  364.     }
  365.     MASTER_LOCK(&deviceQueuePtr->mutex);
  366.     LIST_FORALL((List_Links *) deviceQueuePtr, (List_Links *)statePtr) {
  367.     if (protocol == statePtr->protocol) {
  368.         if (QueueFull(statePtr->queue)) {
  369.         statePtr->stats.drops++;
  370.         } else {
  371.         bcopy(packetPtr,statePtr->queue.packet[statePtr->queue.tail],
  372.               size);
  373.         statePtr->queue.size[statePtr->queue.tail] = size;
  374.         statePtr->queue.tail = NextTail(statePtr->queue);
  375.         if (statePtr->kernel) {
  376.             /*
  377.              * Indirect to a process to pull the packet off of
  378.              * the input queue.  We can't call the protocol handlers
  379.              * directly because they use malloc and free. 
  380.              */
  381.             Proc_CallFunc((void (*)())statePtr->inputProc, 
  382.             (ClientData)statePtr, 0);
  383.         } else {
  384.             Fsio_DevNotifyReader(statePtr->fsReadyToken);
  385.         }
  386.         }
  387.         break;
  388.     }
  389.     }
  390.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  391. }
  392.  
  393. /*
  394.  *----------------------------------------------------------------------
  395.  *
  396.  * DevNet_FsRead --
  397.  *
  398.  *    Read a packet from a network device. This returns the first
  399.  *    packet from the device's input queue, if any.  This returns
  400.  *    data from at most 1 network packet.  If the caller's buffer is
  401.  *    too short, the packet is truncated.
  402.  *
  403.  * Results:
  404.  *    SUCCESS        - if a packet was found in the queue.  
  405.  *    FS_WOULD_BLOCK    - no packets found.
  406.  *
  407.  * Side effects:
  408.  *    Removes the first packet from the queue and copies it into
  409.  *    the receiver's buffer.
  410.  *
  411.  *----------------------------------------------------------------------
  412.  */
  413.  
  414. /*ARGSUSED*/
  415. ReturnStatus
  416. DevNet_FsRead(devicePtr, readPtr, replyPtr)
  417.     Fs_Device    *devicePtr;
  418.     Fs_IOParam    *readPtr;    /* Read parameter block */
  419.     Fs_IOReply    *replyPtr;    /* Return length and signal */ 
  420. {
  421.     ReturnStatus status;
  422.     register DeviceState *statePtr;
  423.     register Address packetPtr;
  424.     register int size;
  425.     DeviceQueueState    *deviceQueuePtr;
  426.  
  427.     statePtr = (DeviceState *) devicePtr->data;
  428.     deviceQueuePtr = (DeviceQueueState *) statePtr->interPtr->devNetData;
  429.  
  430.     MASTER_LOCK(&deviceQueuePtr->mutex);
  431.     if (QueueEmpty(statePtr->queue)) {
  432.     size = 0;
  433.     status = FS_WOULD_BLOCK;
  434.     if (devNetDebug) {
  435.         printf("DevNet_FsRead: empty queue, %d:%d proto 0x%x\n",
  436.                 statePtr->interPtr->netType,
  437.                 statePtr->interPtr->number,
  438.                 statePtr->protocol);
  439.     }
  440.     } else {
  441.     packetPtr = statePtr->queue.packet[statePtr->queue.head];
  442.     size = statePtr->queue.size[statePtr->queue.head];
  443.  
  444.     statePtr->queue.head = NextHead(statePtr->queue);
  445.  
  446.     if (size > readPtr->length) {
  447.         size = readPtr->length;
  448.     }
  449.     bcopy(packetPtr, readPtr->buffer, size);
  450.  
  451.     status = SUCCESS;
  452.     if (devNetDebug) {
  453.         printf("DevNet_FsRead: Found packet %d:%d proto 0x%x, size %d\n",
  454.                 statePtr->interPtr->netType,
  455.                 statePtr->interPtr->number,
  456.                 statePtr->protocol, size);
  457.     }
  458.     }
  459.  
  460.     replyPtr->length = size;
  461.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  462.     return(status);
  463. }
  464.  
  465.  
  466. /*
  467.  *----------------------------------------------------------------------
  468.  *
  469.  * DevNet_FsWrite --
  470.  *
  471.  *    Pass a packet off to the network driver for output.  The driver
  472.  *    maintains a transmit queue so we don't have to.  The protocol
  473.  *    in the output packet header is verified to be the one corresponding
  474.  *    to the device file.
  475.  *
  476.  * Results:
  477.  *    SUCCESS        - the packet was transmitted.
  478.  *    SYS_INVALID_ARG    - packet is too small or the protocol in the
  479.  *              buffer doesn't match the one for the device.
  480.  *
  481.  * Side effects:
  482.  *    Initiates transmission of the packet.
  483.  *
  484.  *----------------------------------------------------------------------
  485.  */
  486.  
  487. /*ARGSUSED*/
  488. ReturnStatus
  489. DevNet_FsWrite(devicePtr, writePtr, replyPtr)
  490.     Fs_Device    *devicePtr;
  491.     Fs_IOParam    *writePtr;    /* Standard write parameter block */
  492.     Fs_IOReply    *replyPtr;    /* Return length and signal */
  493. {
  494.     register DeviceState *statePtr;
  495.     Net_ScatterGather ioVector;
  496.     Net_Interface    *interPtr;
  497.     int            dataSize;
  498.     int            protocol;
  499.     ReturnStatus    status;
  500.  
  501.     statePtr = (DeviceState *) devicePtr->data;
  502.     interPtr = statePtr->interPtr;
  503.     dataSize = writePtr->length - net_NetworkHeaderSize[interPtr->netType];
  504.     if (devNetDebug) {
  505.     printf(
  506.     "DevNet_FsWrite: Writing packet %d:%d proto 0x%x, size %d (%d)\n",
  507.         statePtr->interPtr->netType, statePtr->interPtr->number,
  508.         statePtr->protocol, writePtr->length, dataSize);
  509.     }
  510.     if (dataSize < interPtr->minBytes ||
  511.     dataSize >  interPtr->maxBytes) {
  512.     if (devNetDebug) {
  513.         printf("DevNet_FsWrite: bad dataSize %d, maxBytes %d, minBytes\n",
  514.         dataSize, interPtr->maxBytes, interPtr->minBytes);
  515.     }
  516.     return(SYS_INVALID_ARG);
  517.     }
  518.     status = ProtocolFromPacket((Address) writePtr->buffer, 
  519.             interPtr->netType, &protocol);
  520.     if (status != SUCCESS) {
  521.     printf("DevNet_FsWrite: can't get protocol from packet\n");
  522.     return SYS_INVALID_ARG;
  523.     }
  524.     if (protocol != statePtr->protocol) {
  525.     if (devNetDebug) {
  526.         printf("DevNet_FsWrite: packet protocol %d != device protocol %d\n",
  527.         protocol, statePtr->protocol);
  528.     }
  529.     return(SYS_INVALID_ARG);
  530.     }
  531.     ioVector.bufAddr = (Address)((int)writePtr->buffer + 
  532.     net_NetworkHeaderSize[interPtr->netType]);
  533.     ioVector.length  = dataSize;
  534.     status = Net_RawOutputSync(interPtr, writePtr->buffer, &ioVector, 1);
  535.     replyPtr->length = writePtr->length;
  536.     return(status);
  537. }
  538.  
  539.  
  540. /*
  541.  *----------------------------------------------------------------------
  542.  *
  543.  * DevNet_FsClose --
  544.  *
  545.  *    Close the device.
  546.  *
  547.  * Results:
  548.  *    SUCCESS
  549.  *
  550.  * Side effects:
  551.  *    The protocol state is marked as closed, and any packets on the
  552.  *    input queue are discarded.
  553.  *
  554.  *----------------------------------------------------------------------
  555.  */
  556. /*ARGSUSED*/
  557. ReturnStatus
  558. DevNet_FsClose(devicePtr, useFlags, openCount, writerCount)
  559.     Fs_Device    *devicePtr;    /* Device info. */
  560.     int        useFlags;    /* FS_READ | FS_WRITE */
  561.     int        openCount;
  562.     /* Number of times device still open. */
  563.     int        writerCount;    /* Number of writers still on the device. */
  564. {
  565.     DeviceState        *statePtr;
  566.     DeviceQueueState     *deviceQueuePtr;
  567.     int            i;
  568.  
  569.     statePtr = (DeviceState *) (devicePtr->data);
  570.     deviceQueuePtr = (DeviceQueueState *) statePtr->interPtr->devNetData;
  571.     MASTER_LOCK(&deviceQueuePtr->mutex);
  572.     List_Remove((List_Links *) statePtr);
  573.     if (List_IsEmpty((List_Links *) deviceQueuePtr)) {
  574.     Net_RemovePacketHandler(statePtr->interPtr);
  575.     }
  576.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  577.     for (i=0 ; i< PACKET_QUEUE_LEN ; i++) {
  578.     free ((char *) statePtr->queue.packet[i]);
  579.     }
  580.     free((char *) statePtr);
  581.     devicePtr->data = (ClientData) NIL;
  582.     return(SUCCESS);
  583. }
  584.  
  585.  
  586. /*
  587.  *----------------------------------------------------------------------
  588.  *
  589.  * DevNet_FsSelect --
  590.  *
  591.  *    Perform device-specific select functions on the device.
  592.  *    Always indicates that the device is writable. Indicates the
  593.  *    device is readable if the queue is not empty.
  594.  *
  595.  * Results:
  596.  *    SUCCESS        - the operation was successful.
  597.  *
  598.  * Side effects:
  599.  *    None.
  600.  *
  601.  *----------------------------------------------------------------------
  602.  */
  603.  
  604. /*ARGSUSED*/
  605. ReturnStatus
  606. DevNet_FsSelect(devicePtr, readPtr, writePtr, exceptPtr)
  607.     Fs_Device    *devicePtr;
  608.     int            *readPtr;
  609.     int            *writePtr;
  610.     int            *exceptPtr;
  611. {
  612.     DeviceState        *statePtr;
  613.     DeviceQueueState     *deviceQueuePtr;
  614.  
  615.     statePtr = (DeviceState *) (devicePtr->data);
  616.     deviceQueuePtr = (DeviceQueueState *) statePtr->interPtr->devNetData;
  617.  
  618.     MASTER_LOCK(&deviceQueuePtr->mutex);
  619.  
  620.     if (*readPtr) {
  621.     if (QueueEmpty(statePtr->queue)) {
  622.         *readPtr = 0;
  623.     }
  624.     }
  625.     *exceptPtr = 0;
  626.     MASTER_UNLOCK(&deviceQueuePtr->mutex);
  627.     return(SUCCESS);
  628. }
  629.  
  630.  
  631. /*
  632.  *----------------------------------------------------------------------
  633.  *
  634.  * DevNet_FsIOControl --
  635.  *
  636.  *    Not implemented yet.
  637.  *
  638.  * Results:
  639.  *    SUCCESS        - the operation was successful.
  640.  *    SYS_INVALID_ARG - bad command, or wrong buffer size.
  641.  *
  642.  * Side effects:
  643.  *    None.
  644.  *
  645.  *----------------------------------------------------------------------
  646.  */
  647.  
  648. /*ARGSUSED*/
  649. ReturnStatus
  650. DevNet_FsIOControl(devicePtr, ioctlPtr, replyPtr)
  651.     Fs_Device    *devicePtr;
  652.     Fs_IOCParam *ioctlPtr;
  653.     Fs_IOReply *replyPtr;
  654.  
  655. {
  656.     DeviceState        *statePtr;
  657.     Net_Interface    *interPtr;
  658.     ReturnStatus    status = SUCCESS;
  659.  
  660.     statePtr = (DeviceState *) (devicePtr->data);
  661.     interPtr = statePtr->interPtr;
  662.  
  663.     /*
  664.      * Call the ioctl routine specific to the interface.
  665.      */
  666.     status = (interPtr->ioctl)(interPtr, ioctlPtr, replyPtr);
  667.  
  668.     /*
  669.      * Here should be the handling of any ioctls that are specific to
  670.      * the protocol or network devices in general.
  671.      */
  672.  
  673.     return status;
  674. }
  675.  
  676. /*
  677.  *----------------------------------------------------------------------
  678.  *
  679.  * ProtocolFromPacket --
  680.  *
  681.  *    Retrieves the protocol from a packet.  For the Ethernet
  682.  *    the protocol is the type field in the header.  In general
  683.  *    the protocol can be an arbitrary characteristic of the
  684.  *    packet.  
  685.  *
  686.  * Results:
  687.  *    The protocol associated with the packet.
  688.  *
  689.  * Side effects:
  690.  *    None.
  691.  *
  692.  *----------------------------------------------------------------------
  693.  */
  694.  
  695. static ReturnStatus
  696. ProtocolFromPacket(packetPtr, netType, protoPtr)
  697.     Address        packetPtr;    /* Network-specific packet. */
  698.     Net_NetworkType    netType;    /* Type of network. */
  699.     int            *protoPtr;    /* Place to return protocol. */
  700. {
  701.     int            protocol = 0;
  702.     ReturnStatus    status = SUCCESS;
  703.  
  704.     switch(netType) {
  705.     case NET_NETWORK_ETHER:
  706.         protocol = NET_ETHER_HDR_TYPE(*(Net_EtherHdr *)packetPtr);
  707.         break;
  708.     case NET_NETWORK_ULTRA:
  709.         protocol = 0;
  710.         break;
  711.     case NET_NETWORK_FDDI:
  712.         protocol = 0;  
  713.         break;
  714.     default:
  715.         status = FAILURE;
  716.     }
  717.     if (status == SUCCESS) {
  718.     *protoPtr = protocol;
  719.     }
  720.     return status;
  721. }
  722.  
  723. /*
  724.  *----------------------------------------------------------------------
  725.  *
  726.  * ProtocolFromDevice--
  727.  *
  728.  *    Determine the protocol number from the protocol field in the
  729.  *    device unit number.  This is also a function of the network
  730.  *    type.
  731.  *
  732.  * Results:
  733.  *    SUCCESS if the protocol was found, FAILURE otherwise.
  734.  *
  735.  * Side effects:
  736.  *    None.
  737.  *
  738.  *----------------------------------------------------------------------
  739.  */
  740.  
  741. static ReturnStatus
  742. ProtocolFromDevice(unitProto, interPtr, protoPtr)
  743.     int            unitProto;    /* Value of proto field in unit. */
  744.     Net_Interface     *interPtr;    /* Network interface. */
  745.     int            *protoPtr;    /* Place to return protocol. */
  746. {
  747.     static int    mapping[NET_NUM_NETWORK_TYPES][DEV_NET_NUM_PROTO] = {
  748.  
  749.     /* NET_NETWORK_ETHER */ 
  750.         {0, /* Doesn't match any. */
  751.          NET_ETHER_ARP, 
  752.          NET_ETHER_REVARP,
  753.          NET_ETHER_IP, 
  754.          NET_ETHER_SPRITE_DEBUG,
  755.          NET_ETHER_MOP},
  756.     /* NET_NETWORK_ULTRA */
  757.         {0, /* Doesn't match any. */
  758.          0,
  759.          0,
  760.          0},
  761.     /* NET_NETWORK_FDDI */
  762.         {0, /* Doesn't match any. */
  763.          0,
  764.          0,
  765.          0,
  766.              0,
  767.              0}
  768.      };
  769.  
  770.     if (unitProto < 0 || unitProto >= DEV_NET_NUM_PROTO) {
  771.     return FAILURE;
  772.     }
  773.     *protoPtr = mapping[interPtr->netType][unitProto];
  774.     return SUCCESS;
  775. }
  776.  
  777. /*
  778.  *----------------------------------------------------------------------
  779.  *
  780.  * QueueFromInterface --
  781.  *
  782.  *    This routine gets the queue structure from the interface if
  783.  *    one exists, or allocates one otherwise.  We need to have 
  784.  *    this separate routine because many devices share the same
  785.  *    queue structure of an interface and we have to avoid race
  786.  *    conditions when two devices are opened.
  787.  *
  788.  * Results:
  789.  *    Pointer to the queue structure.
  790.  *
  791.  * Side effects:
  792.  *    The queue structure is allocated.
  793.  *
  794.  *----------------------------------------------------------------------
  795.  */
  796.  
  797. static DeviceQueueState *
  798. QueueFromInterface(interPtr)
  799.     Net_Interface    *interPtr;  /* The network interface. */
  800. {
  801.     static Sync_Lock  lock = Sync_LockInitStatic("QueueFromInterface:lock");
  802. #define LOCKPTR (&lock)
  803.  
  804.     DeviceQueueState *deviceQueuePtr;
  805.  
  806.     LOCK_MONITOR;
  807.     deviceQueuePtr = (DeviceQueueState *) interPtr->devNetData;
  808.     if (deviceQueuePtr == (DeviceQueueState *) NIL) {
  809.     deviceQueuePtr = (DeviceQueueState *) 
  810.                 malloc(sizeof(DeviceQueueState));
  811.     List_Init((List_Links *) deviceQueuePtr);
  812.     Sync_SemInitDynamic(&deviceQueuePtr->mutex, 
  813.         "Dev:queueStateMutex");
  814.     interPtr->devNetData = (ClientData) deviceQueuePtr;
  815.     }
  816.     UNLOCK_MONITOR;
  817.     return deviceQueuePtr;
  818. }
  819.  
  820.